package org.kwisatz.nodistun;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;


class RemoteProxyServer extends Thread
{
	private static final Logger logger=Logger.getLogger(RemoteProxyServer.class.getName());
	private int port;
	private Map<Long, Socket> map = new HashMap<Long, Socket>();
	RemoteProxyServer(int port)
	{
		this.port=port;
	}
	
	public void run()
	{
		try
		{
			ServerSocket server=new ServerSocket(port);
			while(true)
			{
				Socket s = server.accept();
				InputStream in = s.getInputStream();
				OutputStream out = s.getOutputStream();
				int command = in.read();
				if(command==1)
				{					
					int llogin = in.read();
					byte[] login = new byte[llogin];
					in.read(login);
					int lpasswd = in.read();
					byte[] passwd = new byte[lpasswd];
					in.read(passwd);
					byte[] hostBuffer = new byte[6];
					in.read(hostBuffer);
					String ip = hostBuffer[0]+"."+hostBuffer[1]+ '.' +hostBuffer[2]+ '.' +hostBuffer[3];
					int port = 256 * hostBuffer[4] + hostBuffer[5];
					long id = System.nanoTime();
					while(map.get(id) != null)
						id++;
					
					logger.info("Connecting to "+ip+ ':' +port+". Session ID is "+id);
					DataOutputStream dout = new DataOutputStream(out);
					dout.writeLong(id);
					dout.flush();
										
					Socket remoteSocket = new Socket(ip, port);
					map.put(id, remoteSocket);
					
					OutputStream remoteOut = remoteSocket.getOutputStream();
					InputStream remoteIn = remoteSocket.getInputStream();
					PipeStream pipe1 = new PipeStream("RemoteProxyServer<-", remoteIn, out);
					pipe1.setDebug(true);
					pipe1.start();
					PipeStream pipe2 = new PipeStream("RemoteProxyServer->", in, remoteOut);
					pipe2.setDebug(true);
					pipe2.start();
				}
				else if(command == 2)
				{
					int llogin = in.read();
					byte[] login = new byte[llogin];
					in.read(login);
					int lpasswd = in.read();
					byte[] passwd = new byte[lpasswd];
					in.read(passwd);
					
					DataInputStream din = new DataInputStream(in);
					long id = din.readLong();

					logger.info("Reconnecting. Session ID is "+id);
																
					Socket remoteSocket = map.get(id);
					OutputStream remoteOut = remoteSocket.getOutputStream();
					InputStream remoteIn = remoteSocket.getInputStream();
					PipeStream pipe1 = new PipeStream("RemoteProxyServer<-", remoteIn, out);
					pipe1.setDebug(true);
					pipe1.start();
					PipeStream pipe2 = new PipeStream("RemoteProxyServer->", in, remoteOut);
					pipe2.setDebug(true);
					pipe2.start();
				}
			}
		}
		catch(IOException ex)
		{
			ex.printStackTrace();
		}
	}		
}